package com.simulation.service;

import com.simulation.engine.ScriptEngine;
import com.simulation.model.DataPoint;
import com.simulation.model.SimulationTask;
import com.simulation.model.SimulationTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

//import javax.annotation.PreDestroy;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

@Service
public class SimulationTaskManager implements DisposableBean {
    private static final Logger logger = LoggerFactory.getLogger(SimulationTaskManager.class);
    
    private final Map<String, SimulationTask> tasks = new ConcurrentHashMap<>();
    private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(10);
    
    @Autowired
    private ScriptEngine scriptEngine;
    
    @Autowired
    private OpcuaServerService opcuaServerService;

    /**
     * 创建新的模拟任务
     */
    public String createTask(String taskName, SimulationTemplate template) {
        String taskId = UUID.randomUUID().toString();
        SimulationTask task = new SimulationTask(taskId, template.getTemplateId(), taskName, template);
        
        // 初始化数据点值
        for (DataPoint dataPoint : template.getDataPoints()) {
            task.updateValue(dataPoint.getPointName(), dataPoint.getInitialValue());
        }
        
        tasks.put(taskId, task);
        logger.info("Created simulation task: {} ({})", taskName, taskId);
        
        return taskId;
    }

    /**
     * 启动模拟任务
     */
    public boolean startTask(String taskId) {
        SimulationTask task = tasks.get(taskId);
        if (task == null) {
            logger.warn("Task not found: {}", taskId);
            return false;
        }

        if (task.getStatus() == SimulationTask.TaskStatus.RUNNING) {
            logger.warn("Task already running: {}", taskId);
            return false;
        }

        task.setStatus(SimulationTask.TaskStatus.RUNNING);
        task.setStartTime(LocalDateTime.now());

        // 为每个数据点创建调度任务
        for (DataPoint dataPoint : task.getTemplate().getDataPoints()) {
            int cycle = dataPoint.getSimulationCycle() != null ? 
                dataPoint.getSimulationCycle() : 1000;
            
            executorService.scheduleAtFixedRate(
                () -> executeDataPointSimulation(task, dataPoint),
                0, cycle, TimeUnit.MILLISECONDS
            );
        }

        logger.info("Started simulation task: {}", taskId);
        return true;
    }

    /**
     * 停止模拟任务
     */
    public boolean stopTask(String taskId) {
        SimulationTask task = tasks.get(taskId);
        if (task == null) {
            logger.warn("Task not found: {}", taskId);
            return false;
        }

        task.setStatus(SimulationTask.TaskStatus.STOPPED);
        
        // 清理脚本上下文
        scriptEngine.cleanupContext(taskId);
        
        logger.info("Stopped simulation task: {}", taskId);
        return true;
    }

    /**
     * 删除模拟任务
     */
    public boolean deleteTask(String taskId) {
        if (stopTask(taskId)) {
            tasks.remove(taskId);
            logger.info("Deleted simulation task: {}", taskId);
            return true;
        }
        return false;
    }

    /**
     * 切换任务模拟模式（正常/异常）
     */
    public boolean toggleTaskMode(String taskId) {
        SimulationTask task = tasks.get(taskId);
        if (task == null) {
            logger.warn("Task not found: {}", taskId);
            return false;
        }

        SimulationTask.SimulationMode newMode = task.getMode() == SimulationTask.SimulationMode.NORMAL ?
            SimulationTask.SimulationMode.ABNORMAL : SimulationTask.SimulationMode.NORMAL;
        
        task.setMode(newMode);
        logger.info("Task {} mode changed to: {}", taskId, newMode);
        return true;
    }

    /**
     * 调整数据点的数值
     */
    public boolean adjustDataPointValue(String taskId, String pointName, Object newValue) {
        SimulationTask task = tasks.get(taskId);
        if (task == null) {
            logger.warn("Task not found: {}", taskId);
            return false;
        }

        task.updateValue(pointName, newValue);
        
        // 同步到OPC UA服务器
        try {
            opcuaServerService.updateValue(task.getTemplate().getOpcuaPath(), pointName, newValue);
        } catch (Exception e) {
            logger.error("Failed to update OPC UA value for {}:{}", taskId, pointName, e);
        }
        
        logger.debug("Adjusted value for {}:{} = {}", taskId, pointName, newValue);
        return true;
    }

    /**
     * 获取所有任务列表
     */
    public List<SimulationTask> getAllTasks() {
        // 更新运行时间
        tasks.values().forEach(this::updateTaskRuntime);
        return new ArrayList<>(tasks.values());
    }

    /**
     * 获取指定任务
     */
    public SimulationTask getTask(String taskId) {
        SimulationTask task = tasks.get(taskId);
        if (task != null) {
            updateTaskRuntime(task);
        }
        return task;
    }

    /**
     * 执行数据点模拟
     */
    private void executeDataPointSimulation(SimulationTask task, DataPoint dataPoint) {
        if (task.getStatus() != SimulationTask.TaskStatus.RUNNING) {
            return;
        }

        try {
            boolean isAbnormal = task.getMode() == SimulationTask.SimulationMode.ABNORMAL;
            Object newValue = scriptEngine.executeScript(task, dataPoint, isAbnormal);
            
            // 更新任务中的值
            task.updateValue(dataPoint.getPointName(), newValue);
            
            // 同步到OPC UA服务器
            opcuaServerService.updateValue(task.getTemplate().getOpcuaPath(), 
                dataPoint.getPointName(), newValue);
            
        } catch (Exception e) {
            logger.error("Error executing simulation for task {} point {}: {}", 
                task.getTaskId(), dataPoint.getPointName(), e.getMessage());
            task.setStatus(SimulationTask.TaskStatus.ERROR);
        }
    }

    /**
     * 更新任务运行时间
     */
    private void updateTaskRuntime(SimulationTask task) {
        if (task.getStatus() == SimulationTask.TaskStatus.RUNNING) {
            Duration duration = Duration.between(task.getStartTime(), LocalDateTime.now());
            task.setRunDuration(duration.toMillis());
        }
    }

    /**
     * 获取任务统计信息
     */
    public Map<String, Object> getTaskStatistics() {
        Map<String, Object> stats = new HashMap<>();
        
        long totalTasks = tasks.size();
        long runningTasks = tasks.values().stream()
            .mapToLong(task -> task.getStatus() == SimulationTask.TaskStatus.RUNNING ? 1 : 0)
            .sum();
        long stoppedTasks = tasks.values().stream()
            .mapToLong(task -> task.getStatus() == SimulationTask.TaskStatus.STOPPED ? 1 : 0)
            .sum();
        long errorTasks = tasks.values().stream()
            .mapToLong(task -> task.getStatus() == SimulationTask.TaskStatus.ERROR ? 1 : 0)
            .sum();
        
        stats.put("totalTasks", totalTasks);
        stats.put("runningTasks", runningTasks);
        stats.put("stoppedTasks", stoppedTasks);
        stats.put("errorTasks", errorTasks);
        
        return stats;
    }

//    @PreDestroy
    public void shutdown() {
        logger.info("Shutting down simulation task manager...");
        
        // 停止所有任务
        tasks.keySet().forEach(this::stopTask);
        
        // 关闭执行器
        executorService.shutdown();
        try {
            if (!executorService.awaitTermination(30, TimeUnit.SECONDS)) {
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            executorService.shutdownNow();
            Thread.currentThread().interrupt();
        }
        
        // 清理脚本引擎
        scriptEngine.cleanupAllContexts();
        
        logger.info("Simulation task manager shutdown completed");
    }

    @Override
    public void destroy() throws Exception {
        shutdown();
    }
}